package com.props.starter.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.props.starter.config.PropsManagementProperties;
import com.props.starter.model.ConfigVersion;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class VersionService {

    private final PropsManagementProperties properties;
    private final ObjectMapper objectMapper;
    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss");

    public VersionService(PropsManagementProperties properties) {
        this.properties = properties;
        this.objectMapper = new ObjectMapper();
        // 配置时间序列化
        this.objectMapper.findAndRegisterModules();
        this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    }

    /**
     * 保存配置文件版本
     */
    public ConfigVersion saveVersion(String fileName, String content, String comment) {
        if (!StringUtils.hasText(properties.getVersionDir())) {
            log.warn("Version directory not configured, skipping version save");
            return null;
        }

        try {
            Path versionDir = Paths.get(properties.getVersionDir());
            if (!Files.exists(versionDir)) {
                Files.createDirectories(versionDir);
            }

            // 获取下一个版本号
            int nextVersion = getNextVersionNumber(fileName);
            
            // 生成版本ID和文件名
            String timestamp = LocalDateTime.now().format(formatter);
            String versionId = fileName + "_v" + nextVersion + "_" + timestamp;
            String versionFileName = versionId + getFileExtension(fileName);
            
            Path versionFilePath = versionDir.resolve(versionFileName);
            
            // 保存配置文件副本
            Files.write(versionFilePath, content.getBytes(StandardCharsets.UTF_8));
            
            // 创建版本信息
            ConfigVersion configVersion = new ConfigVersion();
            configVersion.setVersionId(versionId);
            configVersion.setFileName(fileName);
            configVersion.setVersionNumber(nextVersion);
            configVersion.setComment(comment);
            configVersion.setCreateTime(LocalDateTime.now());
            configVersion.setVersionFilePath(versionFilePath.toString());
            configVersion.setFileSize(content.getBytes(StandardCharsets.UTF_8).length);
            
            // 保存版本元数据
            saveVersionMetadata(configVersion);
            
            // 清理旧版本
            cleanupOldVersions(fileName);
            
            log.info("Saved version {} for file: {}", nextVersion, fileName);
            return configVersion;
            
        } catch (Exception e) {
            log.error("Error saving version for file: " + fileName, e);
            return null;
        }
    }

    /**
     * 获取文件的所有版本
     */
    public List<ConfigVersion> getVersions(String fileName) {
        if (!StringUtils.hasText(properties.getVersionDir())) {
            return Collections.emptyList();
        }

        try {
            Path versionDir = Paths.get(properties.getVersionDir());
            if (!Files.exists(versionDir)) {
                return Collections.emptyList();
            }

            Path metadataFile = versionDir.resolve(fileName + "_versions.json");
            if (!Files.exists(metadataFile)) {
                return Collections.emptyList();
            }

            String jsonContent = Files.readString(metadataFile, StandardCharsets.UTF_8);
            ConfigVersion[] versions = objectMapper.readValue(jsonContent, ConfigVersion[].class);
            
            return Arrays.stream(versions)
                    .sorted((v1, v2) -> v2.getCreateTime().compareTo(v1.getCreateTime()))
                    .collect(Collectors.toList());
                    
        } catch (Exception e) {
            log.error("Error getting versions for file: " + fileName, e);
            return Collections.emptyList();
        }
    }

    /**
     * 获取指定版本的内容
     */
    public Map<String, String> getVersionContent(String versionId) {
        if (!StringUtils.hasText(properties.getVersionDir())) {
            return null;
        }

        try {
            Path versionDir = Paths.get(properties.getVersionDir());
            
            // 查找版本文件
            String fileName = extractFileNameFromVersionId(versionId);
            String extension = getFileExtension(fileName);
            Path versionFilePath = versionDir.resolve(versionId + extension);
            
            if (Files.exists(versionFilePath)) {
                String content = Files.readString(versionFilePath, StandardCharsets.UTF_8);
                
                // 解析文件内容为配置Map
                return parseConfigContent(content, fileName);
            }
            
        } catch (Exception e) {
            log.error("Error getting version content for: " + versionId, e);
        }
        
        return null;
    }

    /**
     * 解析配置文件内容为Map
     */
    private Map<String, String> parseConfigContent(String content, String fileName) {
        Map<String, String> configs = new HashMap<>();
        
        try {
            if (fileName.endsWith(".properties")) {
                // 解析 properties 文件
                Properties props = new Properties();
                props.load(new StringReader(content));
                for (String key : props.stringPropertyNames()) {
                    configs.put(key, props.getProperty(key));
                }
            } else if (fileName.endsWith(".yml") || fileName.endsWith(".yaml")) {
                // 解析 YAML 文件
                ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
                Map<String, Object> yamlMap = yamlMapper.readValue(content, Map.class);
                flattenMap(yamlMap, "", configs);
            }
        } catch (Exception e) {
            log.error("Error parsing config content for file: " + fileName, e);
        }
        
        return configs;
    }

    /**
     * 递归展平嵌套的Map结构
     */
    private void flattenMap(Map<String, Object> source, String prefix, Map<String, String> target) {
        for (Map.Entry<String, Object> entry : source.entrySet()) {
            String key = prefix.isEmpty() ? entry.getKey() : prefix + "." + entry.getKey();
            Object value = entry.getValue();
            
            if (value instanceof Map) {
                flattenMap((Map<String, Object>) value, key, target);
            } else if (value instanceof List) {
                List<?> list = (List<?>) value;
                for (int i = 0; i < list.size(); i++) {
                    Object listItem = list.get(i);
                    if (listItem instanceof Map) {
                        flattenMap((Map<String, Object>) listItem, key + "[" + i + "]", target);
                    } else {
                        target.put(key + "[" + i + "]", String.valueOf(listItem));
                    }
                }
            } else {
                target.put(key, String.valueOf(value));
            }
        }
    }

    /**
     * 删除指定版本
     */
    public boolean deleteVersion(String fileName, String versionId) {
        if (!StringUtils.hasText(properties.getVersionDir())) {
            return false;
        }

        try {
            Path versionDir = Paths.get(properties.getVersionDir());
            
            // 删除版本文件
            String extension = getFileExtension(fileName);
            Path versionFilePath = versionDir.resolve(versionId + extension);
            if (Files.exists(versionFilePath)) {
                Files.delete(versionFilePath);
            }
            
            // 更新元数据 - 创建可变列表
            List<ConfigVersion> versions = getVersions(fileName);
            List<ConfigVersion> mutableVersions = new ArrayList<>(versions);
            mutableVersions.removeIf(v -> v.getVersionId().equals(versionId));
            saveVersionsMetadata(fileName, mutableVersions);
            
            log.info("Deleted version {} for file: {}", versionId, fileName);
            return true;
            
        } catch (Exception e) {
            log.error("Error deleting version " + versionId + " for file: " + fileName, e);
            return false;
        }
    }

    private int getNextVersionNumber(String fileName) {
        List<ConfigVersion> versions = getVersions(fileName);
        return versions.isEmpty() ? 1 : versions.stream()
                .mapToInt(ConfigVersion::getVersionNumber)
                .max()
                .orElse(0) + 1;
    }

    private String getFileExtension(String fileName) {
        int lastDot = fileName.lastIndexOf('.');
        return lastDot >= 0 ? fileName.substring(lastDot) : "";
    }

    private String extractFileNameFromVersionId(String versionId) {
        // versionId format: fileName_v1_20231201_123456
        int firstUnderscore = versionId.indexOf('_');
        return firstUnderscore >= 0 ? versionId.substring(0, firstUnderscore) : versionId;
    }

    private void saveVersionMetadata(ConfigVersion configVersion) throws IOException {
        List<ConfigVersion> versions = getVersions(configVersion.getFileName());
        // 创建一个可变的ArrayList来避免UnsupportedOperationException
        List<ConfigVersion> mutableVersions = new ArrayList<>(versions);
        mutableVersions.add(configVersion);
        saveVersionsMetadata(configVersion.getFileName(), mutableVersions);
    }

    private void saveVersionsMetadata(String fileName, List<ConfigVersion> versions) throws IOException {
        Path versionDir = Paths.get(properties.getVersionDir());
        Path metadataFile = versionDir.resolve(fileName + "_versions.json");
        
        try {
            String jsonContent = objectMapper.writerWithDefaultPrettyPrinter()
                    .writeValueAsString(versions);
            Files.write(metadataFile, jsonContent.getBytes(StandardCharsets.UTF_8), 
                       StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
            log.debug("Saved metadata for {} versions of file: {}", versions.size(), fileName);
        } catch (Exception e) {
            log.error("Failed to save version metadata for file: " + fileName, e);
            throw new IOException("Failed to save version metadata: " + e.getMessage(), e);
        }
    }

    private void cleanupOldVersions(String fileName) {
        try {
            List<ConfigVersion> versions = getVersions(fileName);
            if (versions.size() > properties.getMaxVersions()) {
                // 按创建时间排序，保留最新的版本
                versions.sort((v1, v2) -> v2.getCreateTime().compareTo(v1.getCreateTime()));
                
                List<ConfigVersion> versionsToDelete = versions.subList(properties.getMaxVersions(), versions.size());
                for (ConfigVersion version : versionsToDelete) {
                    deleteVersion(fileName, version.getVersionId());
                }
            }
        } catch (Exception e) {
            log.error("Error cleaning up old versions for file: " + fileName, e);
        }
    }
} 